/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the demonstration applications of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "mini2440client.h"

Mini2440Client::Mini2440Client(QStringList* args)
{
    initDefaultValue();
    initComponent();
    initSocket();
    initConnection();
    initConfiguration();
}

void Mini2440Client::initDefaultValue()
{
    currentIndex = 0;
    m_config = new mini2440Configuration();
    m_config->loadConfig();
}

void Mini2440Client::initComponent()
{
    currentIndex = -1;

    usInboxIndex            = INBOX;
    gpioBell = new GPIO(PIN32);
    gpioBell->openPin();
    gpioBell->setDirection(GPIO::Out);
    gpioBell->setState(false);

    lock = new GPIO(PIN20);
    lock->openPin();
    lock->setDirection(GPIO::Out);
    gpioBell->setState(false);

    //init picture flow widget
    pictureFlowWidget       = new PictureFlow();
    addWidget(pictureFlowWidget);
    //init screen save widget
    screenSaveWidget        = new ScreenSave();
    screenSaveWidget->addImageDir(m_config->getScreenImageDir());
    screenSaveWidget->setSlideInterval(m_config->get_screenInterval());
    addWidget(screenSaveWidget);
    //init message screen show widget
    messageSlideShowWidget  = new MessageScreenSave();
    messageSlideShowWidget->addImageDir(m_config->getMessageImageDir());
    addWidget(messageSlideShowWidget);

    //init timer
    inputTimer = new QTimer();
    inputTimer->setSingleShot(true);
    inputTimer->setInterval(m_config->get_screenTimeout());

    //door timer
    doorTimer = new QTimer();
    doorTimer->setSingleShot(true);

    qDebug() << m_config->get_autolock();
    doorTimer->setInterval(m_config->get_autolock());
    //set current active widget
    setCurrentWidget(pictureFlowWidget);
    pictureFlowWidget->setFocus();

    QRect screen_size = QApplication::desktop()->screenGeometry();
    const int h = screen_size.height() * SIZING_FACTOR_HEIGHT;
    const int w = screen_size.width() * SIZING_FACTOR_WIDTH;
    const int hh = qMin(h, w);
    const int ww = hh / 3 * 2;
    pictureFlowWidget->setSlideSize(QSize(ww, hh));
    populatePictureFlow();
}

void Mini2440Client::initConfiguration()
{
    if (true)
    {
      screenSaveWidget->setPassword(m_config->get_currentPass());
      pictureFlowWidget->setPassword(m_config->get_currentPass());
      messageSlideShowWidget->setPassword(m_config->get_currentPass());
      //this->setMinimumSize(500,600);
      showFullScreen();
      //this->showMinimized();
      inputTimer->start();
    } else {
        pictureFlowWidget->setAttribute(Qt::WA_DeleteOnClose, true);
        pictureFlowWidget->close();
    }
}

void Mini2440Client::initConnection()
{
    tcpSocket = new QTcpSocket(this);
    tcpSocket->connectToHost(m_config->getServerIP(),m_config->getServerPort());

    ////qDebug() << m_config->getServerIP() << m_config->getServerPort();
    QObject::connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(recievedData()));
    //QObject::connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onDisconnect()));
    QObject::connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(onDisconnect()));

    QObject::connect(pictureFlowWidget,     SIGNAL(itemActivated(int)),
                     this, SLOT(launchApplication(int)));
    QObject::connect(pictureFlowWidget,     SIGNAL(inputReceived()),
                     this, SLOT(resetInputTimeout()));
    QObject::connect(pictureFlowWidget,     SIGNAL(slideActived()),
                     this, SLOT(inputTimedout()));
    QObject::connect(pictureFlowWidget,     SIGNAL(newMessage()),
                     this, SLOT(recievedNewMessageSignal()));
    QObject::connect(pictureFlowWidget,     SIGNAL(wrongpass()),
                     this, SLOT(recievedWrogpassSignal()));
    QObject::connect(pictureFlowWidget,     SIGNAL(ringTheBell()),
                     this, SLOT(recievedRingTheBellSignal()));
    QObject::connect(pictureFlowWidget,     SIGNAL(stopRingTheBell()),
                     this, SLOT(recievedStopRingTheBellSignal()));
    QObject::connect(pictureFlowWidget,     SIGNAL(openDoor()),
                     this, SLOT(recievedOpenDoorSignal()));
    QObject::connect(pictureFlowWidget,     SIGNAL(closeDoor()),
                     this, SLOT(recievedCloseDoorSignal()));

    QObject::connect(screenSaveWidget,      SIGNAL(inputReceived()),
                     this, SLOT(switchToLauncher()));
    QObject::connect(screenSaveWidget,       SIGNAL(newMessage()),
                     this, SLOT(recievedNewMessageSignal()));
    QObject::connect(screenSaveWidget,     SIGNAL(wrongpass()),
                     this, SLOT(recievedWrogpassSignal()));
    QObject::connect(screenSaveWidget,     SIGNAL(ringTheBell()),
                     this, SLOT(recievedRingTheBellSignal()));
    QObject::connect(screenSaveWidget,     SIGNAL(stopRingTheBell()),
                     this, SLOT(recievedStopRingTheBellSignal()));
    QObject::connect(screenSaveWidget,     SIGNAL(openDoor()),
                     this, SLOT(recievedOpenDoorSignal()));
    QObject::connect(screenSaveWidget,     SIGNAL(closeDoor()),
                     this, SLOT(recievedCloseDoorSignal()));

    QObject::connect(messageSlideShowWidget, SIGNAL(readNewMessage()),
                     this, SLOT(recievedReadNewMessageSignal()));
    QObject::connect(messageSlideShowWidget,     SIGNAL(wrongpass()),
                     this, SLOT(recievedWrogpassSignal()));
    QObject::connect(messageSlideShowWidget,     SIGNAL(ringTheBell()),
                     this, SLOT(recievedRingTheBellSignal()));
    QObject::connect(messageSlideShowWidget,     SIGNAL(stopRingTheBell()),
                     this, SLOT(recievedStopRingTheBellSignal()));
    QObject::connect(messageSlideShowWidget,     SIGNAL(openDoor()),
                     this, SLOT(recievedOpenDoorSignal()));
    QObject::connect(messageSlideShowWidget,     SIGNAL(closeDoor()),
                     this, SLOT(recievedCloseDoorSignal()));

    QObject::connect(mOutside,     SIGNAL(openDoor()),
                     this, SLOT(recievedOpenDoorSignal()));
    QObject::connect(mOutside,     SIGNAL(closeDoor()),
                     this, SLOT(recievedCloseDoorSignal()));

    QObject::connect(inputTimer,             SIGNAL(timeout()),
                     this, SLOT(inputTimedout()));
    QObject::connect(doorTimer,             SIGNAL(timeout()),
                     this, SLOT(doorTimedout()));

    QObject::connect(mSetting,SIGNAL(saveSetting()),this,SLOT(updateConfig()));
    QObject::connect(mChangePass,SIGNAL(saveSetting()),this,SLOT(updateConfig()));
}

void Mini2440Client::initSocket()
{

}

Mini2440Client::~Mini2440Client()
{
    delete pictureFlowWidget;
    delete screenSaveWidget;
    delete messageSlideShowWidget;
    delete m_config;
    delete mInbox;
    delete mSetting;
    delete mChangePass;
    delete mOutside;
    gpioBell->closePin();
    delete gpioBell;
    lock->closePin();
    delete lock;
    tcpSocket->disconnectFromHost();
    tcpSocket->abort();
}

void Mini2440Client::recievedData()
{
    QByteArray block;
    QTextCodec* codec = QTextCodec::codecForName("UTF-16LE");
    QDataStream in(&block, QIODevice::ReadOnly);
    in.setVersion(QDataStream::Qt_4_0);
    in.setByteOrder(QDataStream::LittleEndian);

    block = tcpSocket->read(14);
    int totalBytes = 0;
    quint16 command = 0x000;
    in >> totalBytes >> command;// >> len1 >> len2;
    switch(command)
    {
    case 0x114:
        m_config->resetPass();
        QMessageBox::about(0,"FUEMES Server",QString::fromUtf8("Mật khẩu đã được reset"));
        break;
    case 0x115:
       // temp = QDir::currentPath().toStdString();
        int len1,len2;
        len1 = 0;
        len2 = 0;
        in >> len1 >> len2;
        if ((len1+len2+10) != totalBytes)
            return;
        block = tcpSocket->read(len1);
        QString subject = codec->toUnicode(block);
        block = tcpSocket->read(len2);
        QString content = codec->toUnicode(block);
        //save file
        QFile file(subject+".msg");
        QDir::setCurrent(MESSAGE_DIR_PATH);
        if (!file.open(QFile::WriteOnly | QFile::Text)) {
            QMessageBox::warning(this, tr("Application"),
                                 tr("Cannot write file %1:\n%2.")
                                 .arg(subject)
                                 .arg(file.errorString()));
            return ;
        }

        QString path = QDir::currentPath();
        path.remove(path.length()-9,9);
       // QDir::setCurrent(QString().fromStdString(temp));
        QDir::setCurrent(path);
        QTextStream out(&file);
    #ifndef QT_NO_CURSOR
        QApplication::setOverrideCursor(Qt::WaitCursor);
    #endif
        out << content;
    #ifndef QT_NO_CURSOR
        QApplication::restoreOverrideCursor();
    #endif
        recievedNewMessageSignal();
        break;
    }
}

bool Mini2440Client::sendCommand(int command)
{
    if (tcpSocket->state() != QAbstractSocket::ConnectedState)
        return false;
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_0);

    out.setByteOrder(QDataStream::LittleEndian);
    out << command;

    tcpSocket->write(block);
    return true;
}

void Mini2440Client::populatePictureFlow()
{
    pictureFlowWidget->setSlideCount(4);

    mInbox = new mini2440InboxForm();
    appList.append(mInbox);
    pictureFlowWidget->setSlide(INBOX,*( new QImage(INBOX_ICON_PATH)));
    pictureFlowWidget->setSlideCaption(INBOX, QString::fromUtf8("Hộp Thư"));

    mOutside = new mini2440OutsideDeviceControlForm();
    appList.append(mOutside);
    pictureFlowWidget->setSlide(CAMERA,*( new QImage(CAMERA_ICON_PATH)));
    pictureFlowWidget->setSlideCaption(CAMERA, QString::fromUtf8("Camera"));

    mSetting = new mini2440SettingForm();
    mSetting->setConfig(m_config);
    appList.append(mSetting);
    pictureFlowWidget->setSlide(SETUP,*( new QImage(SETTING_ICON_PATH)));
    pictureFlowWidget->setSlideCaption(SETUP, QString::fromUtf8("Cài đặt"));

    mChangePass = new mini2440ChangePassForm();
    mChangePass->setConfig(m_config);
    appList.append(mChangePass);
    pictureFlowWidget->setSlide(CHANGEPASS,*( new QImage(CHANGEPASS_ICON_PATH)));
    pictureFlowWidget->setSlideCaption(CHANGEPASS, QString::fromUtf8("Đổi mật khẩu"));

    /*appList.append(new QWidget());
    pictureFlowWidget->setSlideCaption(QUIT, QString::fromUtf8("Thoát"));*/
    pictureFlowWidget->setCurrentSlide(INBOX);
}

void Mini2440Client::launchApplication(int index)
{
    // NOTE: Clearing the caches will free up more memory for the demo but will cause
    // a delay upon returning, as items are reloaded.
    //pictureFlowWidget->clearCaches();
    /*
    if (index == appList.size() -1) {
        qApp->quit();
        return;
    }*/
    currentIndex = index;
    inputTimer->stop();

    if (index == INBOX )
    {
        pictureFlowWidget->setSlide(INBOX, QImage(INBOX_ICON_PATH));
        mInbox->find();
    }
    appList[index]->showFullScreen();
}

void Mini2440Client::switchToLauncher()
{
    if (currentIndex != -1)
        appList[currentIndex]->close();
    screenSaveWidget->stopShow();
    messageSlideShowWidget->stopShow();
    inputTimer->start();
    setCurrentWidget(pictureFlowWidget);
    pictureFlowWidget->setFocus();
    raise();
    activateWindow();
}

void Mini2440Client::recievedNewMessageSignal()
{
    if (currentIndex == INBOX)
        return;
    inputTimer->stop();
    messageSlideShowWidget->startShow();
    setCurrentWidget(messageSlideShowWidget);
    messageSlideShowWidget->setFocus();
}

void Mini2440Client::recievedReadNewMessageSignal()
{
    pictureFlowWidget->setSlide(usInboxIndex, QImage(INBOX_NEW_ICON_PATH));
    pictureFlowWidget->setCurrentSlide(INBOX);
    switchToLauncher();
}

void Mini2440Client::resetInputTimeout()
{
    if (inputTimer->isActive())
        inputTimer->start();
}

void Mini2440Client::inputTimedout()
{
    switchToSlideshow();
}

void Mini2440Client::doorTimedout()
{
    qDebug() << "door closed!";
    lock->setState(false);
    sendCommand(COMMAND_DOOR_CLOSE);
    return;
}

void Mini2440Client::recievedWrogpassSignal()
{
    ////qDebug() << "wrong pass controller";
    sendCommand(COMMAND_DOOR_WRONGPASS);
    if (0)
        QMessageBox::information(this, tr("Fortune Client"),
                                 tr("The connection was refused by the peer. "
                                    "Make sure the fortune server is running, "
                                    "and check that the host name and port "
                                    "settings are correct."));
}

void Mini2440Client::recievedRingTheBellSignal()
{
    gpioBell->setState(true);
    //if (currentIndex == CAMERA)
    //    return;
    ////qDebug() << "ring the bell";
    switchToLauncher();
    //launchApplication(CAMERA);
}

void Mini2440Client::recievedStopRingTheBellSignal()
{
    gpioBell->setState(false);
    //if (currentIndex == CAMERA)
    //    return;
    ////qDebug() << "ring the bell";
    switchToLauncher();
    //launchApplication(CAMERA);
}

void Mini2440Client::recievedOpenDoorSignal()
{
    qDebug() << "door open!";
    lock->setState(true);
    sendCommand(COMMAND_DOOR_OPEN);
    doorTimer->start();
    return;
    if (!sendCommand(COMMAND_DOOR_OPEN))
        QMessageBox::information(this, tr("Fortune Client"),
                                 tr("The connection was refused by the peer. "
                                    "Make sure the fortune server is running, "
                                    "and check that the host name and port "
                                    "settings are correct."));
}

void Mini2440Client::recievedCloseDoorSignal()
{
    lock->setState(false);
    sendCommand(COMMAND_DOOR_CLOSE);
    doorTimer->stop();
    return;
    if (!sendCommand(COMMAND_DOOR_CLOSE))
        QMessageBox::information(this, tr("Fortune Client"),
                                 tr("The connection was refused by the peer. "
                                    "Make sure the fortune server is running, "
                                    "and check that the host name and port "
                                    "settings are correct."));
}

void Mini2440Client::switchToSlideshow()
{
    inputTimer->stop();
    screenSaveWidget->startShow();
    setCurrentWidget(screenSaveWidget);
    screenSaveWidget->setFocus();
}

void Mini2440Client::demoFinished()
{
    currentIndex = -1;
    setCurrentWidget(pictureFlowWidget);
    inputTimer->start();

    // Bring the Fluidlauncher to the foreground to allow selecting another demo
    raise();
    activateWindow();
}

void Mini2440Client::changeEvent(QEvent* event)
{
    if (event->type() == QEvent::ActivationChange) {
        if (isActiveWindow()) {
            if(currentWidget() == pictureFlowWidget) {
                resetInputTimeout();
            } else if(currentWidget() ==screenSaveWidget ){
                screenSaveWidget->startShow();
            }
            else
            {
                messageSlideShowWidget->startShow();
            }
        } else {
            inputTimer->stop();
            screenSaveWidget->stopShow();
            messageSlideShowWidget->stopShow();
        }
    }
    QStackedWidget::changeEvent(event);
}

void Mini2440Client::displayError(QAbstractSocket::SocketError socketError)
{
    switch (socketError) {
    case QAbstractSocket::RemoteHostClosedError:
        break;
    case QAbstractSocket::HostNotFoundError:
        QMessageBox::information(this, tr("Fortune Client"),
                                 tr("The host was not found. Please check the "
                                    "host name and port settings."));
        break;
    case QAbstractSocket::ConnectionRefusedError:
        QMessageBox::information(this, tr("Fortune Client"),
                                 tr("The connection was refused by the peer. "
                                    "Make sure the fortune server is running, "
                                    "and check that the host name and port "
                                    "settings are correct."));
        break;
    default:
        QMessageBox::information(this, tr("Fortune Client"),
                                 tr("The following error occurred: %1.")
                                 .arg(tcpSocket->errorString()));
    }

    //getFortuneButton->setEnabled(true);
}

void Mini2440Client::onDisconnect()
{
    return;
    while(1)
    {
        tcpSocket->connectToHost(m_config->getServerIP(),m_config->getServerPort());
        if (tcpSocket->waitForConnected(1000))
            break;
    }
    return;
}

void Mini2440Client::updateConfig()
{
    //qDebug() << m_config->get_screenTimeout();
    inputTimer->setInterval(m_config->get_screenTimeout());
    screenSaveWidget->setSlideInterval(m_config->get_screenInterval());
    screenSaveWidget->setPassword(m_config->get_currentPass());
    pictureFlowWidget->setPassword(m_config->get_currentPass());
    messageSlideShowWidget->setPassword(m_config->get_currentPass());
    qDebug() << m_config->get_autolock();
    doorTimer->setInterval(m_config->get_autolock());
    doorTimer->stop();
    doorTimer->start();
    inputTimer->stop();
    inputTimer->start();
}
